package com.heakey.common.component;

import cn.hutool.core.util.ObjectUtil;
import com.heakey.common.constant.CommonConstant;
import org.springframework.stereotype.Service;

import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description 抽样检测服务(避免大量检测提高性能)
 * @Author Bing
 * @Date 2025/4/8 19:37
 */
@Service
public class SpotCheckService {
    // 缓存计数器
    private final ConcurrentHashMap<String, WeakReference<AtomicInteger>> COUNTERS = new ConcurrentHashMap<>();
    // 触发检测间隔
    private final int TRIGGER_STEP = 15;
    // 最大并发数(避免用锁)
    private final int MAX_CONCURRENCY = 1000;
    // 避免溢出
    private final int MAX_COUNTER = Integer.MAX_VALUE - MAX_CONCURRENCY;

    /**
     * 抽样检测
     * @param key
     * @return
     */
    public boolean toCheck(String key){
        // 获取或创建计数器
        WeakReference<AtomicInteger> counter = COUNTERS.computeIfAbsent(key, k -> new WeakReference(new AtomicInteger(CommonConstant.NUM_ZERO)));
        int count = 0;
        // 避免溢出
        AtomicInteger atomicInteger = counter.get();
        // 如果被回收了则重新计算
        if(ObjectUtil.isNull(atomicInteger)){
            return false;
        }
        if((count = atomicInteger.incrementAndGet()) >= MAX_COUNTER){
            atomicInteger.set(CommonConstant.NUM_ZERO);
            return true;
        }
        // 触发检测间隔
        if(count % TRIGGER_STEP == CommonConstant.NUM_ZERO){
            return true;
        }
        return false;
    }

    /**
     * 清理某个键的计数器
     * @param key
     */
    public void clear(String key){
        COUNTERS.remove(key);
    }

    /**
     * 清理某个键的计数器
     */
    public void clearAll(){
        COUNTERS.clear();
    }
}